
package data;

import guiDisplay.UserData;
import guiDisplay.UserData2;
import guiDisplay.MovieList;

import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

import logic.Encriptor;

import sql.SQLUtilityManagement;



public class SystemSqlDatabase extends SystemData{

	public SystemSqlDatabase(){
		SQLUtilityManagement.init();
	}

	@Override
	public void addMovie(MovieTuple movie) {
		SQLUtilityManagement.addMovie(movie);
	}

	@Override
	public void addRating(String user, String movie, String rating, String description) {
		MovieTuple movieTuple = SQLUtilityManagement.getMovie(movie);
		double newRating = (movieTuple.get_raters()*movieTuple.get_rating() + Integer.parseInt(rating))/(movieTuple.get_raters()+1);
		SQLUtilityManagement.addRating(user,movie,rating,description,GregorianCalendar.getInstance().getTime().toString());
		SQLUtilityManagement.updateMovieRating(movie, newRating+"", (movieTuple.get_raters()+1)+"");

	}

	@Override
	public boolean addUser(UserTuple user) {
		return SQLUtilityManagement.addUser(user);
	}

	@Override
	public void changeUserPassword(String name, String password) {
		SQLUtilityManagement.updateUserPassword(name, password);
	}

	@Override
	public UserTuple createUser(String name, String pw, String sex, String bdate, String type) {
		String encryptedpass;
		try {
			encryptedpass = Encriptor.encryptUserPassword(pw);
			UserTuple user = new UserTuple(name , encryptedpass , sex , bdate , type);
			if (SQLUtilityManagement.addUser(user)){
				return user;
			} else {
				return null;
			}
		}catch(NoSuchAlgorithmException e){
			e.printStackTrace();
			return null;
		}

	}

	@Override
	public void deleteMovie(MovieTuple movie) {
		 SQLUtilityManagement.deleteMovie(movie.get_name());
	}

	@Override
	public void deleteRating(String movieName, String userName) {
		RatingTuple ratingTuple = SQLUtilityManagement.getRating(movieName, userName);
		MovieTuple movieTuple = SQLUtilityManagement.getMovie(movieName);
		double newRating;
		if (movieTuple.get_raters()==0)
			newRating = 0;
		else
			newRating = (movieTuple.get_raters()*movieTuple.get_rating() - ratingTuple.get_rating())/(movieTuple.get_raters()-1);
		SQLUtilityManagement.deleteRating(userName, movieName);
		SQLUtilityManagement.updateMovieRating(movieName, newRating+"", (movieTuple.get_raters()-1)+"");
	}

	@Override
	public void deleteUser(UserTuple user) {
		TreeSet<RatingTuple> rat = SQLUtilityManagement.getRatingsByUser(user.get_name());
		for (RatingTuple r: rat){
			deleteRating(r.get_movie().get_name(), user.get_name());
		}
		SQLUtilityManagement.deleteUser(user.get_name());
	}

	@Override
	public void editRating(String user, String movie, String description, String rate, String date) {
		RatingTuple ratingTuple = SQLUtilityManagement.getRating(movie, user);
		MovieTuple movieTuple = SQLUtilityManagement.getMovie(movie);
		double newRating = (movieTuple.get_raters()*movieTuple.get_rating() - ratingTuple.get_rating() + Integer.parseInt(rate))/(movieTuple.get_raters());
		SQLUtilityManagement.setRating(user, movie , rate , description, date);
		SQLUtilityManagement.updateMovieRating(movie, newRating+"");
	}

	@Override
	public void editUser(String name, String bdate, String sex) {
		SQLUtilityManagement.updateUserDetails(name, bdate, sex);
	}

	@Override
	public MovieTuple getMovie(String movie) {
		return SQLUtilityManagement.getMovie(movie);
	}

	@Override
	@Deprecated
	public RatingTuple getRandomRec() {
		return null;
	}

	@Override
	public RatingTuple getRating(String user, String movie) {
		return SQLUtilityManagement.getRating(movie, user);
	}

	@Override
	public TreeSet<RatingTuple> getRatingsByMovie(String movie) {
		return SQLUtilityManagement.getRatingsByMovie(movie);
	}

	@Override
	public TreeSet<RatingTuple> getRatingsByUser(String user) {
		return SQLUtilityManagement.getRatingsByUser(user);
	}

	@Override
	public UserTuple getUser(String user) {
		return SQLUtilityManagement.getUser(user);
	}

	@Override
	public Set<MovieTuple> getAllMovies() {
		return SQLUtilityManagement.getAllMovies();
	}

	@Override
	public Set<UserTuple> getAllUsers() {
		return SQLUtilityManagement.getAllUsers();
	}

	@Override
	public Set<RatingTuple> getAllRatings() {
		return SQLUtilityManagement.getAllRating();
	}

	@Override
	public void exit() {
	}

	@Override
	public String[] getMovieNames() {
		return SQLUtilityManagement.getMovieNames();
	}

	@Override
	public MovieList getMovieNames(int start) {
		String[] movies = SQLUtilityManagement.getMovieNames();
		int numOfMovies = movies.length;
		Arrays.sort(movies);
		movies = Arrays.copyOfRange(movies, Math.min(start, movies.length-10), Math.min(start+10, movies.length));
		System.out.println(movies.length);
		return new MovieList(numOfMovies, movies);
	}

	@Override
	public String[] getUserNames(String username) {
		return SQLUtilityManagement.getUserNames(username);
	}
	@Override
	public String[] getRegUserNames() {
		return SQLUtilityManagement.getRegUserNames();
	}

	@Override
	public String[] getAllNames() {
		return SQLUtilityManagement.getAllNames();
	}

	@Override
	public UserData getUserData(String user) {
		UserTuple myuser = SQLUtilityManagement.getUser(user);
		StringTokenizer bd = new StringTokenizer(myuser.get_bdate(), "/");
		return new UserData(user, myuser.is_sex(),bd.nextToken(), bd.nextToken(), bd.nextToken(), -1 );
	}

	@Override
	public MovieList search(String str, int start) {
		String[] _allMovies= SystemData.getInstance().getMovieNames();
		Arrays.sort(_allMovies);
		int count=0;
		String[] tmp;
		if(str.length()==1 && !Character.isDigit(str.charAt(0))){
			tmp = new String[_allMovies.length];
			for(int i=0; i<_allMovies.length; i++){
				if(_allMovies[i].toLowerCase().startsWith(str.toLowerCase())){
					tmp[count]=_allMovies[i];
					count++;
				}
			}

		}
		else{
			String[] lc = new String[_allMovies.length];
			for(int i=0; i<_allMovies.length; i++){
				lc[i]=_allMovies[i].toLowerCase();
			}
			tmp = new String[_allMovies.length];
			for(int i=0; i<_allMovies.length; i++){
				if(lc[i].contains(str.toLowerCase())){
					tmp[count]=_allMovies[i];
					count++;
				}
			}
		}
		String[] _searchMovies = new String[Math.min(count, 10)];
		for(int i=start; i<start+Math.min(count,10); i++){
			_searchMovies[i-start]=tmp[i];
		}
		MovieList ans = new MovieList(Math.min(count, 10), _searchMovies);
		return ans;
	}


	@Override
	public MovieTuple[] getUserMovies(String user, int minRating) {
		return SQLUtilityManagement.getUserMovies(user,minRating);
	}

	@Override
	public UserData2[] getMovieRaters(String movie, int minRating) {
		return SQLUtilityManagement.getMovieRaters(movie, minRating);
	}

	@Override
	public MovieTuple[] getNMovies(int n, boolean highest) {
		return SQLUtilityManagement.getNMovies(n, highest);
	}

	@Override
	public void setAdmin(String name) {
		SQLUtilityManagement.setAdmin(name);
	}

	@Override
	public void setManager(String name) {
		SQLUtilityManagement.setManager(name);

	}

	@Override
	public String[] getNotMngUsersNames() {
		return SQLUtilityManagement.getNotMngUserNames();
	}

	@Override
	public double getAvg(String user) {
		return SQLUtilityManagement.getAvg(user);
	}


}


